﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.XPath;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Globalization;
using SpLocalizer.Common;
using SpLocalizer.Common.DbApi;

namespace SpLocalizer.ContentSourceProviders.XPath
{
    public class XPathContent : AbstractContent
    {

        public string[] XPath {get;set;}
      
        /// <summary>
        /// XPath Navigator
        /// </summary>
        protected XPathNavigator XPathNav { 
            get {
                return XmlDoc.CreateNavigator();
            }
        }


       protected XmlDocument XmlDoc { get; set; }

       protected string TaskLanguage = String.Empty;

       public XPathContent(string[] XPath)
        {
            this.XPath = XPath;
        }

       public virtual void Bind (string XmlFilePath)
        {
            this.XmlDoc = new XmlDocument();
            XmlDoc.PreserveWhitespace = true;
            this.XmlDoc.Load(XmlFilePath);
            this.ContentAddress = XmlFilePath;
        }

        public override IEnumerable<BaseTranslationTask> BuildTranslationTasks(CultureInfo FromLanguage, CultureInfo ToLanguage)
        {
            // Select all book nodes that have the matching attribute value.
            List<BaseTranslationTask> tasksToTranslate = new List<BaseTranslationTask>();
            
            foreach (string xPathString in XPath)
            {
                XPathNodeIterator ni = XPathNav.Select(xPathString);
                while (ni.MoveNext())
                {
                    // We don't wona translate empty strings
                    if (ni.Current != null && !string.IsNullOrEmpty(ni.Current.Value) && !string.IsNullOrEmpty(ni.Current.Value.Trim()))
                    {
                        XPathContentLocalizationTask tt = new XPathContentLocalizationTask(FromLanguage, ToLanguage,
                            xPathString, ni.CurrentPosition);
                        tt.SourceText = ni.Current.Value;
                        tt.Status = TranslationTaskStatus.Initialized;
                        tt.Format = isTaskContainHtml(tt) ? Constants.TASK_FORMAT_HTML : Constants.TASK_FORMAT_TEXT;
                        tasksToTranslate.Add(tt);
                    }
                }
            }
            

            return tasksToTranslate;
        }


        protected static bool isTaskContainHtml(XPathContentLocalizationTask task)
        {
            Regex tagRegex = new Regex(@"<\s*([^ >]+)[^>]*>.*?<\s*/\s*\1\s*>");
            return tagRegex.IsMatch(task.SourceText);
        }


        public override void ExportContentTranslations(BaseTranslationTask TranslationTask)
        {
            TaskLanguage = TranslationTask.ToLanguage.Name; // Set language name from tasks

         /*  XmlNodeList nodeList =  XmlDoc.SelectNodes(((XPathContentLocalizationTask)TranslationTask).XPath);
             int NodeIndex = int.Parse(((XPathContentLocalizationTask)TranslationTask).Position);
             XmlNode node = nodeList.Item(NodeIndex);

             // check if source text the same
             if (!TranslationTask.SourceText.Equals(node.Value))
                 throw new ApplicationException(String.Format("URI: {0} source text:\n {1} \n doesnt match database source:\n {2}",
                     node.BaseURI, node.Value, TranslationTask.SourceText));

             node.Value = TranslationTask.TranslatedText;*/
            XPathNodeIterator iterator = XPathNav.Select(((XPathContentLocalizationTask)TranslationTask).XPath);
              int NodeIndex = int.Parse(((XPathContentLocalizationTask)TranslationTask).Position);
            
            while (iterator.CurrentPosition < NodeIndex) // Position Navigator
                            iterator.MoveNext();

            // check if source text the same
            if (!TranslationTask.SourceText.Equals(iterator.Current.Value))
                throw new ApplicationException(String.Format("URI: {0} source text:\n {1} \n doesnt match database source:\n {2}",
                    iterator.Current.BaseURI, iterator.Current.Value, TranslationTask.SourceText));

            iterator.Current.SetValue(TranslationTask.TranslatedText);
        }

        public override void PerformExportDone()
        {
            if (string.IsNullOrEmpty(this.TaskLanguage))
                return;

            FileInfo fi = new FileInfo(this.ContentAddress);
            DirectoryInfo dir = fi.Directory; //.CreateSubdirectory(this.TaskLanguage);
            using (XmlWriter xw = XmlWriter.Create(dir.FullName + "\\" + fi.Name))
            {               
                XmlDoc.WriteTo(xw);//XPathNav.WriteSubtree(xw);
            }
        }
    }
}
